package com.zzyk.main.utils;

import com.zzyk.main.configuration.exception.UserException;
import com.zzyk.main.model.vo.Message;


import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;

/**
 * 验证码生成工具 网上找的 又改了改
 */
public class CaptchaUtils {
    private static final String[] FONT_TYPES = {"宋体", "新宋体", "黑体", "楷体", "隶书"};

    /**
     * 验证码生成
     * 这里返回Message 因为没法同时返回图片和验证码信息
     * 验证码信息又不用存数据库
     * 项目又没用到redis
     *
     * @param width  图片宽度
     * @param height 图片高度
     * @return {code:验证码的文字,img:验证码的图像}
     */
    public static Message generate(int width, int height, int length) throws UserException {
        try (ByteArrayOutputStream byteOut = new ByteArrayOutputStream()) {
            String code = generate(width, height, length, byteOut);
            Message message = Message.success();
            message.addData("code", code);
            message.addData("img", byteOut.toByteArray());
            return message;
        } catch (IOException e) {
            throw new UserException("生成验证码失败");
        }
    }

    /**
     * 生成验证码图片
     *
     * @param width  图片宽度
     * @param height 图片高度
     * @param os     输出到哪去
     * @return 随机字符
     * @throws IOException
     */

    private static String generate(int width, int height, int length, OutputStream os) throws IOException {
        String randomStr = RandomUtils.randomString(length);
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics = image.createGraphics();
        image = graphics.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
        graphics = image.createGraphics();
        drawBackground(graphics, width, height);
        drawRandomLine(graphics, width, height, 8);
        drawRandomChar(graphics, width, randomStr);
        graphics.dispose();
        //设置PNG格式
        ImageIO.write(image, "png", os);
        return randomStr;
    }

    // 填充背景色
    private static void drawBackground(Graphics2D graphics, int width, int height) {
        // 填充背景
        graphics.setColor(new Color(255, 255, 255, 0));
        // 设置矩形坐标x y 为0
        graphics.fillRect(0, 0, width, height);
    }

    // 加入干扰线条
    private static void drawRandomLine(Graphics2D graphics, int width, int height, int number) {
        for (int i = 0; i < number; i++) {
            //设置随机颜色算法参数
            graphics.setColor(RandomUtils.randomColor(40, 150));
            Random random = new Random();
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            int x1 = random.nextInt(width);
            int y1 = random.nextInt(height);
            graphics.drawLine(x, y, x1, y1);
        }
    }

    // 绘制字符
    private static void drawRandomChar(Graphics2D graphics, int width, String randomStr) {
        char[] charArray = randomStr.toCharArray();
        int charWidth = width / randomStr.length();
        for (int i = 0; i < charArray.length; i++) {
            //设置RGB颜色算法参数
            graphics.setColor(randomColor());
            //设置字体大小，类型
            graphics.setFont(new Font(FONT_TYPES[RandomUtils.nextInt(FONT_TYPES.length)], Font.BOLD, 26));
            //设置x y 坐标
            graphics.drawString(String.valueOf(charArray[i]), charWidth * i + 5, 19 + RandomUtils.nextInt(8));
        }
    }

    // 随机颜色 不指定透明度的话就是不透明
    private static Color randomColor() {
        return randomColor(0xFF);
    }

    // 随机颜色
    private static Color randomColor(int alpha) {
        return new Color(
                RandomUtils.nextInt(255),
                RandomUtils.nextInt(255),
                RandomUtils.nextInt(255),
                alpha
        );
    }

}
